// @Author miaoqing
// @Date 2024/02/22 15:58:00
// @Desc
package logic

import (
	"core/common"
	"core/component/function"
	"core/component/idgenerator"
	"core/component/logger"
	"core/component/timer"
	"core/ini"
	"core/network"
	"net"
	_ "net/http/pprof"
	"runtime/debug"
	"strconv"
	"sync"
	"sync/atomic"
	"time"
)

var (
	server *Server
	once   sync.Once
)

const (
	httpService     = "gateway-http"
	tcpService      = "gateway-tcp"
	innerTCPService = "gateway-innertcp"
)

type Server struct {
	network.Service
	id           string
	tcpServer    *network.TcpServer
	tcpSvcID     string
	tcpPort      int
	tcpAddr      string
	innerServer  *network.TcpServer
	innerSvcID   string
	innerSrvAddr string
	innerPort    int
	innerAddr    string
	httpAddr     string
	httpPort     int
	httpHandler  *HTTPHandler
	timer        *timer.Timer
	conf         *ini.Config
	stopping     atomic.Bool
}

func ServerInstance() *Server {
	once.Do(func() {
		server = &Server{
			tcpServer:   &network.TcpServer{},
			timer:       timer.NewTimer(),
			innerServer: &network.TcpServer{},
			httpHandler: newHttpHandler(),
		}
		server.Impl = server
	})
	return server
}

func (srv *Server) Run() {
	srv.tcpServer.NewClient = func(conn net.Conn) network.IConn {
		cli := &Client{
			NetConn: network.NewNetConn(conn, 1024),
		}
		cli.Init()
		cli.Impl = cli
		return cli
	}

	srv.innerServer.NewClient = func(conn net.Conn) network.IConn {
		cli := &OnlineClient{
			NetConn: network.NewNetConn(conn, 512*1024),
		}
		cli.Init()
		cli.Impl = cli
		return cli
	}

	startHTTPServer(srv.httpAddr, srv.httpHandler)

	// 启动tcp服务器
	go srv.tcpServer.Run()

	//启动内部服务器
	go srv.innerServer.Run()

	srv.serviceRegister()
	go func() {
		tick := time.NewTicker(time.Second * 1)
		defer func() {
			tick.Stop()
			if err := recover(); err != nil {
				logger.Error("[异常] 全局定时器出错", err, "\n", string(debug.Stack()))
			}
		}()

		for {
			select {
			case <-tick.C:
				srv.timer.Loop()
			}
		}
	}()
}

func (srv *Server) Init(cfg interface{}, processIdx int) {
	c, ok := cfg.(*ini.Config)
	if !ok {
		logger.Error("load ini error init !!!")
		return
	}
	srv.conf = c

	srv.httpPort = srv.conf.Server.GatewayHttpPort + processIdx
	srv.httpAddr = srv.conf.Server.GatewayHttpIp + ":" + strconv.Itoa(srv.httpPort)
	srv.id = strconv.FormatUint(function.IpAddressStringToUint64(srv.httpAddr), 10)

	srv.tcpPort = srv.conf.Server.GatewayTcpPort + processIdx
	srv.tcpAddr = srv.conf.Server.GatewayTcpIp + ":" + strconv.Itoa(srv.tcpPort)
	srv.tcpServer.Init(srv.tcpAddr)

	srv.innerPort = srv.conf.Server.InnerGatewayTcpPort + processIdx
	srv.innerSrvAddr = srv.conf.Server.InnerGatewayTcpIp + ":" + strconv.Itoa(srv.innerPort)
	srv.innerServer.Init(srv.innerSrvAddr)
	srv.registerTimer()

	logger.Infof("GatewayID:%v pidx:%v", srv.id, processIdx)
}

func (srv *Server) registerTimer() {
	srv.timer.RegTimer(srv.registerGatewayServerTimer, 1*time.Second)
	srv.timer.RegTimer(srv.registerTcpServerTimer, 1*time.Second)
}

func (srv *Server) Finialize() {
	srv.stopping.Store(true)
	req := &common.RemoveServerReq{ServerID: srv.innerSvcID}
	_ = common.SendCenterHttpRequest(req, nil, "POST", "/removeGatewayServer")

	req1 := &common.RemoveServerReq{ServerID: srv.tcpSvcID}
	_ = common.SendCenterHttpRequest(req1, nil, "POST", "/removeTcpServer")

	srv.tcpServer.Close()
	srv.innerServer.Close()
	logger.Infof("服务器断开连接")

}

func (srv *Server) serviceRegister() {

	// 注册tcp服务
	srv.tcpSvcID = idgenerator.FetchServiceID(tcpService, srv.tcpAddr)
	logger.Infof("gatewayTcpServerID:%v", srv.tcpSvcID)
	//
	// 注册服务器内部tcp服务
	srv.innerSvcID = idgenerator.FetchServiceID(innerTCPService, srv.innerSrvAddr)
	logger.Infof("gatewayInnnerServerID:%v", srv.innerSvcID)

}
